﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using dotnetCHARTING.WinForms;
using Processing001.Library.AbstractClasses;
using Processing001.Library.Interfaces;

namespace Processing001.Library
{
    public class Solution002 : SolutionAbstract<ComplexNumber, GraphicLab002>
    {
        private List<ComplexNumber> y;
        private List<ComplexNumber> z;
        private List<ComplexNumber> h;
        private List<ComplexNumber> k;
        private List<ComplexNumber> Cyk;
        private List<ComplexNumber> Czk;
        private FurieWrapper wrapper;

        public Solution002(int size)
        {
            this.size = size;

            thread = new Thread(new ThreadStart(StartProcess));
        }

        private void StartProcess()
        {
            graphics.Clear();

            Initialize();

            FirstStep();
            SecondStep();

            if (DisplayGraphics != null)
            {
                DisplayGraphics(this, EventArgs.Empty);
            }
        }

        private void Initialize()
        {
            FunctionGenerator yGenerator = new FunctionGenerator(new YFunction(), size);
            FunctionGenerator zGenerator = new FunctionGenerator(new ZFunction(), size);
            y = yGenerator.Generate();
            z = zGenerator.Generate();
            input = yGenerator.Input;

            wrapper = new FurieWrapper(size);
            Cyk = wrapper.GenerateByWay(Way.Right, y);
            Czk = wrapper.GenerateByWay(Way.Right, z);
        }

        private void FirstStep()
        {
            Chart yChart = GenerateChartByTask(GraphicLab002.Y, "Y", y, input, SeriesType.Line);
            Chart zChart = GenerateChartByTask(GraphicLab002.Z, "Z", z, input, SeriesType.Line);
            graphics.Add(GraphicLab002.Y, yChart);
            graphics.Add(GraphicLab002.Z, zChart);
        }

        private void SecondStep()
        {
            h = GetWrapperFunction();
            k = GetKFunction();
            Chart hChart = GenerateChartByTask(GraphicLab002.Wrapper, "H", h, input, SeriesType.Line);
            Chart kChart = GenerateChartByTask(GraphicLab002.Kor, "K", k, input, SeriesType.Line);
            graphics.Add(GraphicLab002.Wrapper, hChart);
            graphics.Add(GraphicLab002.Kor, kChart);
        }

        /// <summary>
        /// Корреляционная функция.
        /// </summary>
        private List<ComplexNumber> GetKFunction()
        {
            List<ComplexNumber> Cinvolve = InvolveArray(Cyk);
            List<ComplexNumber> Cnk = MulValues(Cinvolve, Czk);
            return wrapper.GenerateByWay(Way.Left, Cnk);
        }

        private List<ComplexNumber> InvolveArray(List<ComplexNumber> value)
        {
            List<ComplexNumber> result = new List<ComplexNumber>();
            foreach (ComplexNumber number in value)
            {
                result.Add(number.ToInvolve());
            }
            return result;
        }

        private List<ComplexNumber> GetWrapperFunction()
        {
            List<ComplexNumber> Cyzk = MulValues(Cyk, Czk);
            return wrapper.GenerateByWay(Way.Left, Cyzk);
        }

        private List<ComplexNumber> MulValues(List<ComplexNumber> values1, List<ComplexNumber> values2)
        {
            List<ComplexNumber> result = new List<ComplexNumber>();
            for(int i = 0; i < values1.Count; i++)
            {
                result.Add(values1[i].Mul(values2[i]));
            }
            return result;
        }

        Chart CreateChart(String title, SeriesType type)
        {
            Chart chart = new Chart();
            chart.Title = title;
            chart.Type = ChartType.Scatter;
            chart.Use3D = false;
            chart.Series.DefaultElement.Color = Color.FromArgb(49, 255, 49);
            chart.DefaultSeries.Type = type;
            chart.DefaultSeries.DefaultElement.Marker.Type = ElementMarkerType.None;
            chart.DefaultSeries.DefaultElement.Transparency = 0;
            chart.XAxis.Label.Text = "X";
            chart.YAxis.Label.Text = "Y";
            chart.TempDirectory = "temp";
            chart.Width = 600;
            chart.Height = 350;
            chart.Dock = DockStyle.Fill;
            return chart;
        }

        private Chart GenerateChartByTask(GraphicLab002 graphic, String title,
            List<ComplexNumber> generatedValues, List<ComplexNumber> x, SeriesType type)
        {
            Chart chart = CreateChart(title, type);
            Series series = new Series();
            series.Name = "Series";
            for (int iterator = 0; iterator < generatedValues.Count; iterator++)
            {
                Element element = new Element(iterator.ToString());
                element.Name = "Element" + iterator.ToString();
                element.XValue = x[iterator].Real;
                element.YValue = generatedValues[iterator].Real;
                series.AddElements(element);
            }
            SeriesCollection collection = new SeriesCollection(series);
            chart.SeriesCollection.Add(collection);
            return chart;
        }
    }
}
